import { defineStore } from 'pinia'
import { ElNotification } from 'element-plus'
import { ref } from 'vue'

// 类型定义 ------------------------------------------------------------------------
type WebSocketMessage<T = any> = {
    method: string   // 消息方法类型（用于路由）
    code?: number    // 状态码
    data?: T         // 消息内容
    timestamp?: number // 时间戳
}

type ListenerCallback = (data: any) => void

// WebSocket配置项
interface WebSocketOptions {
    url: string                    // 必须的服务器地址
    autoReconnect?: boolean        // 自动重连（默认true）
    maxRetries?: number            // 最大重试次数（默认5）
    reconnectInterval?: number     // 重连间隔（默认3000ms）
    heartbeatInterval?: number     // 心跳间隔（默认30000ms）
}

// Pinia Store定义 ---------------------------------------------------------------
export const useWebSocketStore = defineStore('websocket', () => {
    // 响应式状态
    const isConnected = ref(false)    // 连接状态
    const isLoading = ref(false)       // 加载状态
    const messageQueue = ref<any[]>([]) // 消息队列
    const listeners = ref<Map<string, ListenerCallback[]>>(new Map()) // 消息监听器

    // 私有属性
    let ws: WebSocket | null = null
    let retries = 0                    // 当前重试次数
    let isManualClose = false          // 是否手动关闭
    let heartbeatTimer = null

    // 默认配置
    const defaultOptions: WebSocketOptions = {
        url: '',
        autoReconnect: true,
        maxRetries: 5,
        reconnectInterval: 3000,
        heartbeatInterval: 30000
    }

    // 当前配置
    const options = ref<WebSocketOptions>(defaultOptions)

    // 方法实现 --------------------------------------------------------------------

    /**
     * 初始化全局WebSocket连接
     * @param config 配置参数
     */
    const initialize = (config: WebSocketOptions) => {
        // 合并配置
        options.value = { ...defaultOptions, ...config }

        // 防止重复初始化
        if (ws) return

        // 创建WebSocket实例
        ws = new WebSocket(options.value.url)

        // 绑定事件处理器
        ws.onopen = handleOpen
        ws.onmessage = handleMessage
        ws.onerror = handleError
        ws.onclose = handleClose

        isLoading.value = true
    }

    // 连接成功处理
    const handleOpen = (event: Event) => {
        isConnected.value = true
        isLoading.value = false
        retries = 0
        flushMessageQueue()
        startHeartbeat()
        const token = localStorage.getItem('token');
        send('LOGIN', { login_token: token })
        ElNotification.success('WebSocket连接成功')
    }

    // 消息处理
    const handleMessage = (event: MessageEvent) => {
        try {
            const message = JSON.parse(event.data)
            console.log(message)
            // 处理服务端主动推送
            if (message.code && message.code !== 200) {
                handleError(message.msg)
            }
            // 触发对应method的监听器
            triggerListeners(message.method, message)
        } catch (error) {
            console.error('消息解析失败:', error)
        }
    }

    // 错误处理
    const handleError = (msg) => {
        isLoading.value = false
        // ElNotification.error(`WebSocket连接错误:${msg}`);
    }

    // 关闭处理
    const handleClose = (event: CloseEvent) => {
        isConnected.value = false
        isLoading.value = false
        clearInterval(heartbeatTimer)

        // 自动重连逻辑
        if (!isManualClose && options.value.autoReconnect) {
            scheduleReconnect()
        }
    }

    // 消息发送 --------------------------------------------------------------------
    /**
     * 发送消息
     * @param method 消息方法类型
     * @param data 消息内容
     */
    const send = <T>(method: string, data?: T) => {
        const payload = JSON.stringify({ method, data })
        if (ws?.readyState === WebSocket.OPEN) {
            ws.send(payload)
        } else {
            messageQueue.value.push(payload)
        }
    }

    // 消息监听 --------------------------------------------------------------------
    /**
     * 注册消息监听器
     * @param method 要监听的消息方法
     * @param callback 回调函数
     */
    const on = (method: string, callback: ListenerCallback) => {
        if (!listeners.value.has(method)) {
            listeners.value.set(method, [])
        }
        listeners.value.get(method)?.push(callback)
    }

    /**
     * 移除消息监听器
     * @param method 要移除监听的消息方法
     * @param callback 要移除的回调函数
     */
    const off = (method: string, callback?: ListenerCallback) => {
        if (!callback) {
            listeners.value.delete(method)
        } else {
            const methods = listeners.value.get(method) || []
            listeners.value.set(
                method,
                methods.filter(fn => fn !== callback)
            )
        }
    }

    // 私有方法 --------------------------------------------------------------------
    // 触发监听器
    const triggerListeners = (method: string, data: any) => {
        listeners.value.get(method)?.forEach(callback => callback(data))
    }

    // 自动重连
    const scheduleReconnect = () => {
        if (retries >= options.value.maxRetries!) {
            ElNotification.error(`已达最大重试次数（${options.value.maxRetries}）`)
            return
        }

        retries++
        setTimeout(() => initialize(options.value), options.value.reconnectInterval)
    }

    // 心跳检测
    const startHeartbeat = () => {
        heartbeatTimer = setInterval(() => {
            if (isConnected.value) {
                send('PING', [])
            }
        }, options.value.heartbeatInterval)
    }

    // 清空消息队列
    const flushMessageQueue = () => {
        while (messageQueue.value.length > 0 && ws?.readyState === WebSocket.OPEN) {
            const message = messageQueue.value.shift()
            ws.send(message)
        }
    }

    return {
        // 状态
        isConnected,
        isLoading,

        // 方法
        initialize,
        send,
        on,
        off,

        // 清理方法
        close: () => {
            isManualClose = true
            ws?.close()
        }
    }
})
// 在组件中使用
// const wsStore = useWebSocketStore()
// wsStore.on('USER_MESSAGE', (data) => {
//   console.log('收到用户消息:', data)
// })
// wsStore.send('ADMIN_COMMAND', { action: 'refresh' })